package com.hm.system.service.mongo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.querydsl.QPageRequest;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.hm.common.common.CommonUtil;
import com.hm.common.exception.ServiceException;
import com.hm.common.model.PageInfo;
import com.hm.system.mongo.domain.def.SysMenuDef;
import com.hm.system.mongo.domain.system.QSysMenuInfo;
import com.hm.system.mongo.domain.system.SysMenuInfo;
import com.hm.system.mongo.vo.system.SysMenuInfoVo;
import com.hm.system.share.repository.mongo.system.SysMenuInfoRepository;
import com.hm.system.share.service.mongo.system.SysMenuInfoService;
import com.mysema.query.types.expr.BooleanExpression;

/**
 * @author shishun.wang
 * @date 2016年5月25日 下午10:54:58
 * @version 1.0
 * @describe
 */
@Service
@SuppressWarnings({ "rawtypes", "unchecked" })
public class SysMenuInfoServiceImpl implements SysMenuInfoService {

	@Autowired
	private SysMenuInfoRepository sysMenuInfoRepository;

	@Override
	public String addSysMenuInfo(SysMenuInfoVo sysMenuInfo, String operationUser) {
		QSysMenuInfo sysmenuinfo = QSysMenuInfo.sysMenuInfo;
		BooleanExpression expression = sysmenuinfo.name.eq(sysMenuInfo.getName())
				.and(sysmenuinfo.code.eq(sysMenuInfo.getCode()));
		Iterator<SysMenuInfo> iterator = sysMenuInfoRepository.findAll(expression).iterator();
		while (iterator.hasNext()) {
			throw ServiceException.warn("菜单名称、菜单CODE不允许重复添加");
		}
		if (CommonUtil.isNotEmpty(sysMenuInfo.getParentId())) {
			if (null == this.getSysMenuInfo(sysMenuInfo.getParentId())) {
				throw ServiceException.warn("上级菜单不存在");
			}
		}

		SysMenuInfo menuInfo = new SysMenuInfo();
		{
			menuInfo.setCreateUser(operationUser);
			menuInfo.setName(sysMenuInfo.getName());
			menuInfo.setCode(sysMenuInfo.getCode());
			menuInfo.setNote(sysMenuInfo.getNote());
			menuInfo.setParentId(sysMenuInfo.getParentId());
			menuInfo.setUrl(sysMenuInfo.getUrl());
			menuInfo.setMenuDef(sysMenuInfo.getMenuDef());
		}

		return sysMenuInfoRepository.save(menuInfo).getId();
	}

	@Override
	public String updateSysMenuInfo(SysMenuInfoVo sysMenuInfo, String operationUser) {
		if (CommonUtil.isNotEmpty(sysMenuInfo.getParentId())) {
			if (null == this.getSysMenuInfo(sysMenuInfo.getParentId())) {
				throw ServiceException.warn("上级菜单不存在");
			}
		}
		SysMenuInfo menuInfo = sysMenuInfoRepository.findOne(sysMenuInfo.getId());
		if (null != menuInfo) {
			menuInfo.setCreateUser(operationUser);
			menuInfo.setName(sysMenuInfo.getName());
			menuInfo.setCode(sysMenuInfo.getCode());
			menuInfo.setNote(sysMenuInfo.getNote());
			menuInfo.setParentId(sysMenuInfo.getParentId());
			menuInfo.setUrl(sysMenuInfo.getUrl());
			menuInfo.setMenuDef(sysMenuInfo.getMenuDef());
		}

		return sysMenuInfoRepository.save(menuInfo).getId();
	}

	@Override
	public SysMenuInfoVo getSysMenuInfo(String id) {
		SysMenuInfo menuInfo = sysMenuInfoRepository.findOne(id);

		SysMenuInfoVo sysMenuInfoVo = new SysMenuInfoVo();
		if (null != menuInfo) {
			sysMenuInfoVo.setId(menuInfo.getId());
			sysMenuInfoVo.setName(menuInfo.getName());
			sysMenuInfoVo.setCode(menuInfo.getCode());
			sysMenuInfoVo.setNote(menuInfo.getNote());
			sysMenuInfoVo.setUrl(menuInfo.getUrl());
			sysMenuInfoVo.setParentId(menuInfo.getParentId());
			if (CommonUtil.isNotEmpty(menuInfo.getParentId())) {
				SysMenuInfoVo parenMenuIfo = getSysMenuInfo(menuInfo.getParentId());
				sysMenuInfoVo.setParentName(null != parenMenuIfo ? parenMenuIfo.getName() : null);
			}
			sysMenuInfoVo.setMenuDef(menuInfo.getMenuDef());

			return sysMenuInfoVo;
		}
		return null;
	}

	@Override
	public String deleteSysMenuInfo(SysMenuInfoVo sysMenuInfo, String operationUser) {
		sysMenuInfoRepository.delete(sysMenuInfo.getId());
		return sysMenuInfo.getId();
	}

	@Override
	public List<Map<String,Object>> childsById(String menuId, SysMenuDef menuDef) {
		QSysMenuInfo sysmenuinfo = QSysMenuInfo.sysMenuInfo;

		BooleanExpression expression = sysmenuinfo.menuDef.eq(menuDef);
		if (StringUtils.isEmpty(menuId)) {
			expression = expression.and(sysmenuinfo.parentId.isNull()).or(sysmenuinfo.parentId.isEmpty());
		} else {
			expression = expression.and("0".equals(menuId)
					? expression.and(sysmenuinfo.parentId.isNull()).or(sysmenuinfo.parentId.isEmpty())
					: sysmenuinfo.parentId.eq(menuId));
		}

		ArrayList<Map<String,Object>> menuInfoVos = new ArrayList<Map<String,Object>>();

		sysMenuInfoRepository.findAll(expression).iterator().forEachRemaining(menuInfo -> {
			Map<String,Object> menu = new HashMap<String,Object>();
			{
				menu.put("id", menuInfo.getId());
				menu.put("name", menuInfo.getName());
				menu.put("isParent", (childsById(menuInfo.getId(), menuDef).size() > 0));
			}
			menuInfoVos.add(menu);
		});

		return menuInfoVos;
	}

	@Override
	public PageInfo<SysMenuInfoVo> querySysMenuInfo(String name, String code, String url, String parentId,
			SysMenuDef menuDef, Long startTime, Long endTime, Integer pageNumber, Integer pageSize) {
		PageInfo<SysMenuInfoVo> pageInfo = new PageInfo<SysMenuInfoVo>(pageNumber, pageSize);

		QSysMenuInfo qSysMenuInfo = QSysMenuInfo.sysMenuInfo;
		Pageable pageable = new QPageRequest(pageInfo.getPageNumber(), pageInfo.getPageSize(),
				qSysMenuInfo.createTime.desc());

		BooleanExpression predicate = qSysMenuInfo.id.isNotNull();
		{
			if (!StringUtils.isEmpty(name)) {
				predicate = predicate.and(qSysMenuInfo.name.like(name));
			}

			if (!StringUtils.isEmpty(code)) {
				predicate = predicate.and(qSysMenuInfo.code.like(code));
			}

			if (!StringUtils.isEmpty(url)) {
				predicate = predicate.and(qSysMenuInfo.url.like(url));
			}

			if (!StringUtils.isEmpty(parentId)) {
				predicate = predicate.and(qSysMenuInfo.parentId.like(parentId));
			}

			if (!StringUtils.isEmpty(menuDef)) {
				predicate = predicate.and(qSysMenuInfo.menuDef.eq(menuDef));
			}

			if (null != startTime && null != endTime) {
				predicate = predicate.and(qSysMenuInfo.createTime.between(startTime, endTime));
			} else if (null != startTime && null == endTime) {
				predicate = predicate.and(qSysMenuInfo.createTime.goe(startTime));
			} else if (null == startTime && null != endTime) {
				predicate = predicate.and(qSysMenuInfo.createTime.loe(startTime));
			}
		}

		Page page = sysMenuInfoRepository.findAll(predicate, pageable);

		List<SysMenuInfoVo> sysMenuInfoVos = new ArrayList<SysMenuInfoVo>();
		List<SysMenuInfo> content = page.getContent();
		for (SysMenuInfo sysMenuInfo : content) {
			SysMenuInfoVo sysMenuInfoVo = new SysMenuInfoVo();
			{
				sysMenuInfoVo.setId(sysMenuInfo.getId());
				sysMenuInfoVo.setName(sysMenuInfo.getName());
				sysMenuInfoVo.setNote(sysMenuInfo.getNote());
				sysMenuInfoVo.setCode(sysMenuInfo.getCode());
				sysMenuInfoVo.setCreateTime(sysMenuInfo.getCreateTime());
				sysMenuInfoVo.setCreateUser(sysMenuInfo.getCreateUser());
				sysMenuInfoVo.setUrl(sysMenuInfo.getUrl());
				sysMenuInfoVo.setParentId(sysMenuInfo.getParentId());
				if (CommonUtil.isNotEmpty(sysMenuInfo.getParentId())) {
					SysMenuInfoVo parenMenuIfo = getSysMenuInfo(sysMenuInfo.getParentId());
					sysMenuInfoVo.setParentName(null != parenMenuIfo ? parenMenuIfo.getName() : "未知");
				}
				sysMenuInfoVo.setMenuDef(sysMenuInfo.getMenuDef());
				sysMenuInfoVo.setMenuDefDes(sysMenuInfo.getMenuDef().desc());
			}

			sysMenuInfoVos.add(sysMenuInfoVo);
		}

		return pageInfo.execute(page, sysMenuInfoVos);
	}

}
